<template>
  <div
    class="lsh-box"
    ref="boxRef">
    <div
      class="lsh-canvas"
      id="canvasBox">
      <div class="lsh-tool-box">
        <div class="lsh-tool-list">
          <IconBtn
            name="scale-shrink"
            @click="hanScale(false)">
          </IconBtn>
          <span class="scale-text">{{ (scale * 100).toFixed() }}%</span>
          <IconBtn
            name="scale-grow"
            @click="hanScale(true)">
          </IconBtn>
          <IconBtn
            name="rotate-left"
            @click="hanRotate(true)">
          </IconBtn>
          <IconBtn
            name="rotate-right"
            @click="hanRotate(false)">
          </IconBtn>
          <IconBtn
            name="edit"
            @click="startPen = !startPen">
            <span>批注</span>
          </IconBtn>
          <IconBtn
            name="clear"
            @click="clear()">
            <span>清空</span>
          </IconBtn>
          <Button
            class="lsh-pen-btn"
            :disabled="!historyUtil.canUndo.value"
            @click="historyUtil.undo()">
            撤销
          </Button>
          <Button
            class="lsh-pen-btn"
            :disabled="!historyUtil.canRedo.value"
            @click="historyUtil.redo()">
            恢复
          </Button>
          <ColorPicker v-model="color" />
          <Button
            class="lsh-pen-btn"
            @click="initImg()">
            切图
          </Button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, onBeforeUnmount, watch } from "vue";
import {
  Leafer,
  PointerEvent,
  Pen,
  DragEvent,
  Image,
  Rect,
  Box,
  Group,
  ImageEvent,
  ZoomEvent,
  ResizeEvent,
  WatchEvent,
  MoveEvent,
} from "leafer-ui";
import testBg1 from "@/assets/images/test-bg.png";
import testBg2 from "@/assets/images/test-bg-2.png";
import { Button, ColorPicker } from "@arco-design/web-vue";
import "@leafer-in/viewport";
import "@leafer-in/view";
import "@leafer-in/animate";
import { useDebounceFn, useElementSize, useResizeObserver } from "@vueuse/core";
import { useHistoryUtil } from "./hooks/useHistoryUtil.ts";
import { nextTick } from "vue";
import SvgIcon from "@/components/SvgIcon/index.vue";
import IconBtn from "./components/icon-btn/index.vue";

let app: Leafer;
let isDrawing = false;
let pen: Pen;
let bgImage: Image;
const scale = ref(1);
const color = ref("#32cd79");
const startPen = ref(!true);
const zoomConfig = {
  step: 0.2,
  min: 0.2,
  max: 5,
  padding: 10,
};
let fitScale = 1;
const boxRef = ref();
const { width, height } = useElementSize(boxRef);
let index = 1;
const historyUtil = useHistoryUtil((v) => {
  pen.set(v);
  // console.log(app.toJSON())
  localStorage.setItem("penData" + index, JSON.stringify(v));
});
const startDrawing = (e: DragEvent) => {
  if (e?.multiTouch) return (isDrawing = false);
  if (startPen.value) {
    isDrawing = true;
    const point = e.getPagePoint();
    pen.setStyle({
      stroke: color.value,
      strokeWidth: 1 || 3 || 10,
      strokeCap: "round",
      strokeJoin: "round",
    });
    pen.moveTo(point.x, point.y);
  }
};

const continueDrawing = (e: DragEvent) => {
  if (e?.multiTouch) return (isDrawing = false);
  if (isDrawing && startPen.value) {
    const point = e.getPagePoint();
    pen.lineTo(point.x, point.y);
  }
};

const stopDrawing = (e: DragEvent) => {
  if (isDrawing && startPen.value) {
    isDrawing = false;
    app.off(DragEvent.DRAG, dragDragHandler);
    app.off(DragEvent.END, stopDrawing);
    historyUtil.commit(pen.toJSON());
  }
};

const dragDragHandler = (e: DragEvent) => {
  continueDrawing(e);
};
const initPen = () => {
  if (pen) {
    app.remove(pen);
  }
  pen = new Pen();
  app.add(pen);
  const penData = localStorage.getItem("penData" + index);
  if (penData) {
    const data = JSON.parse(penData);
    pen.set(data);
    historyUtil.init(data);
  } else {
    historyUtil.init(pen.toJSON());
  }
};
const initImg = () => {
  if (bgImage) {
    app.remove(bgImage);
    app.remove(pen);
  }
  bgImage = new Image({
    url: index === 1 ? testBg1 : testBg2,
    pixelRatio: 3,
  });
  index === 1 ? (index = 2) : (index = 1);
  app.add(bgImage);
  bgImage.once(ImageEvent.LOADED, async () => {
    await nextTick();
    app.zoom("fit", zoomConfig.padding);
    scale.value = 1;
    fitScale = +app.scale;
    app.config.zoom = {
      min: zoomConfig.min * fitScale,
      max: zoomConfig.max * fitScale,
    };
    initPen();
  });
};
const init = () => {
  app = new Leafer({
    view: "canvasBox",
    smooth: true,
    pointer: { touch: true },
    touch: { preventDefault: true },
    type: "design" || "viewport",
    // hittable:false,
    wheel: {
      // disabled:true,
    },
    move: {
      scroll: false,
    },
    usePartRender: false,
    // moveable:true,
  });

  app.on(ZoomEvent.ZOOM, function () {
    scale.value = +app.scale / fitScale;
  });
  app.on(DragEvent.START, (e: DragEvent) => {
    startDrawing(e);
    app.on(DragEvent.DRAG, dragDragHandler);
    app.on(DragEvent.END, stopDrawing);
  });
  initImg();
};

const clear = () => {
  pen.clear();
  historyUtil.commit(pen.toJSON());
};
const hanRotate = (isLeft: boolean) => {
  app.rotateOf("center", isLeft ? -90 : 90);
};
const hanScale = (isAdd: boolean) => {
  const step = zoomConfig.step;
  let newScale = scale.value + (isAdd ? step : -step);
  if (newScale < zoomConfig.min) newScale = zoomConfig.min;
  if (newScale > zoomConfig.max) newScale = zoomConfig.max;
  scale.value = newScale;
  const target = newScale * fitScale;
  app.zoom(target, zoomConfig.padding, false, 0.2);
};
const hanResize = useDebounceFn(() => {
  if (!app.ready) return;
  app.zoom(bgImage, zoomConfig.padding, !true, 0.2);
  scale.value = 1;
}, 300);
watch([() => width.value, () => height.value], hanResize);
onMounted(() => {
  init();
});
</script>

<style scoped lang="less">
.lsh-box {
  position: relative;
  width: 100vw;
  height: 100vh;
  .lsh-tool-box {
    position: absolute;
    z-index: 1;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 100vw;
    display: flex;
    justify-content: center;
    .lsh-tool-list {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 20px;
      flex-wrap: wrap;
      border-radius: 16px;
      background: rgba(0, 0, 0, 0.7);
      backdrop-filter: blur(5px);
      padding: 16px 32px;
      .lsh-pen-btn {
        cursor: pointer;
      }
      .lsh-tool-btn {
        cursor: pointer;
        color: rgba(255, 255, 255, 1);
        color: #fff;
        font-family: "PingFang SC";
        font-size: 14px;
        font-weight: 400;
        display: flex;
        align-items: center;
        gap: 4px;
      }
      .lsh-icon {
        color: #fff;
        font-size: 20px;
      }
      .scale-text {
        width: 38px;
        color: #fff;
        font-family: "PingFang SC";
        font-size: 14px;
        font-weight: 400;
        line-height: normal;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }

  .lsh-canvas {
    width: 100vw;
    height: 100vh;
    // position: absolute;
    // z-index: 50;
    background-color: transparent;
    transform: translateZ(0); /* 强制启用硬件加速 */
  }

  .lsh-page {
    width: 100%;
    height: 100%;
    background-color: #c2650e;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>
